package cn.fintecher.gis.web;


import cn.fintecher.gis.annotation.CurrentOperator;
import cn.fintecher.gis.entity.LayerRelation;
import cn.fintecher.gis.entity.MetadataConfig;
import cn.fintecher.gis.enums.LayerRelate;
import cn.fintecher.gis.exception.BadRequestException;
import cn.fintecher.gis.geoserver.GeoManagerService;
import cn.fintecher.gis.model.MapSpotData;
import cn.fintecher.gis.model.ParsingGeoJsonResults;
import cn.fintecher.gis.model.ParsingShpResults;
import cn.fintecher.gis.model.request.*;
import cn.fintecher.gis.model.response.LayerInfoResponse;
import cn.fintecher.gis.model.session.SessionModel;
import cn.fintecher.gis.postgis.PostGISService;
import cn.fintecher.gis.service.LayerInfoService;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.geotools.filter.text.cql2.CQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/layerInfoController")
@Api(value = "图层管理", description = "图层管理")
public class LayerInfoController {

    private final Logger log = LoggerFactory.getLogger(LayerInfoController.class);

    @Autowired
    private LayerInfoService layerInfoService;

    @Autowired
    private PostGISService postGISService;
    @Autowired
    private GeoManagerService geoManagerService;


    @GetMapping("/queryLayerInfoList")
    @ApiOperation(value = "查询图层信息", notes = "查询图层信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<LayerInfoResponse>> queryLayerInfoList(Pageable pageable, LayerInfoRequest request) {
        Page<LayerInfoResponse> page = layerInfoService.getLayerInfoAll(request, pageable);
        return ResponseEntity.ok().body(page);
    }

    @GetMapping("/getLayerInfoList")
    @ApiOperation(value = "查询图层信息", notes = "查询图层信息")
    public ResponseEntity<List<LayerInfoResponse>> getLayerInfoList(@RequestParam(value = "layerSpace", required = false) String layerSpace) {
        List<LayerInfoResponse> list = layerInfoService.queryLayerInfoList(layerSpace);
        return ResponseEntity.ok().body(list);
    }


    @GetMapping("/getLayerRelation")
    @ApiOperation(value = "根据类型查询图层", notes = "根据类型查询图层")
    public ResponseEntity<List<LayerRelation>> getLayerRelation(@RequestParam(value = "type", required = false) LayerRelate type) {
        List<LayerRelation> layerRelations = layerInfoService.getLayerRelation(type);
        return ResponseEntity.ok().body(layerRelations);
    }


    @GetMapping("/getLayerInfoById")
    @ApiOperation(value = "根据id查询对应的图层信息", notes = "根据id查询对应的图层信息")
    public ResponseEntity<LayerInfoResponse> getLayerInfoById(@RequestParam("id") String id) {
        LayerInfoResponse layerInfoResponse = layerInfoService.queryLayerInfoById(id);
        return ResponseEntity.ok().body(layerInfoResponse);
    }

    @PostMapping("/createLayerInfo")
    @ApiOperation(value = "图层信息的添加", notes = "图层信息的添加")
    public ResponseEntity<Void> createLayerInfo(@RequestBody LayerInfoCreateRequest request,
                                                @ApiIgnore @CurrentOperator SessionModel operator) throws IOException {
        layerInfoService.createLayerInfo(request, operator);
        return ResponseEntity.ok().build();
    }

    @PostMapping("/adjustShow")
    @ApiOperation(value = "修改图层的关系", notes = "修改图层的关系")
    public ResponseEntity<Void> adjustShow(@RequestBody LayerInfoCreateRequest request) {
        layerInfoService.adjustShow(request.getId(), request.getLayerShow());
        return ResponseEntity.ok().build();
    }

    @PostMapping("/editLayerInfo")
    @ApiOperation(value = "图层信息的维护", notes = "图层信息的维护")
    public ResponseEntity<Void> editLayerInfo(@RequestBody LayerInfoCreateRequest request,
                                              @ApiIgnore @CurrentOperator SessionModel operator) throws Exception {
        layerInfoService.editLayerInfo(request, operator);
        return ResponseEntity.ok().build();
    }


    @DeleteMapping("/deleteLayerInfoById")
    @ApiOperation(value = "根据图层id删除对应的信息", notes = "根据图层id删除对应的信息")
    public ResponseEntity<Void> deleteLayerInfoById(@RequestParam("id") String id,
                                                    @RequestParam("layerSpace") String workSpace) throws IOException {
        layerInfoService.deleteLayerInfoById(id, workSpace);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/deleteTempLayer")
    @ApiOperation(value = "删除临时图层", notes = "删除临时图层")
    public ResponseEntity<Void> deleteTempLayer(@RequestParam("layerCode") String layerCode, @RequestParam("layerSpace") String workSpace) throws IOException {
        geoManagerService.deleteLayer(layerCode, workSpace);
        postGISService.removeSchema(layerCode);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/queryLayerAttributeById")
    @ApiOperation(value = "根据图层ID查询所有属性", notes = "根据图层ID查询所有属性")
    public ResponseEntity<List<MetadataConfig>> queryLayerAttributeById(@RequestParam("id") String id) throws IOException {
        LayerInfoResponse layerInfoResponse = layerInfoService.queryLayerInfoById(id);
        return ResponseEntity.ok().body(postGISService.queryLayerAttribute(layerInfoResponse.getLayerCode()));
    }

    @GetMapping("/queryMapSpotByAttr")
    @ApiOperation(value = "通过属性内容查询图斑列表", notes = "根据图层ID查询所有属性")
    public ResponseEntity<List<MapSpotData>> queryMapSpotByAttr(@RequestParam(required = false, name = "cql") String cql, @RequestParam("layerCode") String layerCode) throws IOException, CQLException {
//        LayerInfoResponse layerInfoResponse = layerInfoService.queryLayerInfoById(id);
        return ResponseEntity.ok().body(postGISService.queryMapSpot(cql, layerCode));
    }

    @GetMapping("/intersectionLayer")
    @ApiOperation(value = "对比图层", notes = "对比图层")
    public ResponseEntity<LayerInfoResponse> intersectionLayer(@RequestParam(name = "layerCode1") String layerCode1, @RequestParam(name = "layerCode2") String layerCode2, @RequestParam(name = "styles") String styles, @RequestParam(name = "workspace") String workspace) throws Exception {
        ParsingShpResults result1 = postGISService.intersectionLayer(layerCode1, layerCode2);
        if (!result1.getIsSuccess()) {
            throw new BadRequestException("importShp", result1.getMessage());
        }
        String[] style = styles.split(",");
        List<String> styleList = Lists.newArrayList(style);
        ParsingShpResults result2 = geoManagerService.releaseLayer(result1.getMessage(), result1.getCrs(), styleList, workspace);
        if (!result2.getIsSuccess()) {
            throw new BadRequestException("importShp", result2.getMessage());
        }
        LayerInfoResponse layerInfoResponse = new LayerInfoResponse();
        layerInfoResponse.setLayerCode(result1.getMessage());
        layerInfoResponse.setLayerSpace(workspace);
        layerInfoResponse.setId(result1.getMessage());
        layerInfoResponse.setTableName(result1.getMessage());
        return ResponseEntity.ok().body(layerInfoResponse);
    }


    @PostMapping("/intersectionWkt")
    @ApiOperation(value = "区域图层对比", notes = "区域图层对比")
    public ResponseEntity<ParsingGeoJsonResults> intersectionWkt(@RequestBody IntersectionWktRequest request) throws Exception {
        ParsingShpResults result = postGISService.intersectionWkt(request.getWkt(), request.getLayerCode(), null);
        if (!result.getIsSuccess()) {
            throw new BadRequestException("importShp", result.getMessage());
        }
        String tableName = result.getMessage();
        String geoJson = postGISService.getLayerGeoJson(tableName);
        postGISService.removeSchema(tableName);
        return ResponseEntity.ok().body(new ParsingGeoJsonResults(true, geoJson));
    }


    @GetMapping("/intersectionLayerGeoJson")
    @ApiOperation(value = "对比图层返回GeoJson", notes = "对比图层返回GeoJson")
    public ResponseEntity<ParsingGeoJsonResults> intersectionLayerGeoJson(@RequestParam(name = "layerCode1") String layerCode1, @RequestParam(name = "layerCode2") String layerCode2) throws Exception {
        ParsingGeoJsonResults result = postGISService.intersectionLayerGeoJson(layerCode1, layerCode2);
        if (!result.getIsSuccess()) {
            throw new BadRequestException("intersectionLayerGeoJson", "对比图层出错");
        }
        return ResponseEntity.ok().body(result);
    }

    @PostMapping("/multipleLayerComparisons")
    @ApiOperation(value = "多个图层对比(辅助选址)", notes = "多个图层对比，返回对比图层与所有被对比图层的交集")
    public ResponseEntity<ParsingGeoJsonResults> multipleLayerComparisons(@RequestBody MultipleLayerComparisonsRequest request) throws Exception {
        List<String> middleCodes = new ArrayList<>();
        String layerCode;
        try {
            layerCode = intersectionLayer(request.getMainLayerCode(), request.getLayerCodes(), middleCodes);
        } catch (IOException | CQLException e) {
            for (String middleCode : middleCodes) {
                postGISService.removeSchema(middleCode);
            }
            log.error("", e);
            throw new IOException(e);
        }
        String geoJson = postGISService.getLayerGeoJson(layerCode);
        //这里考虑下删除不删除 还是需要返回图层地址
        postGISService.removeSchema(layerCode);
        return ResponseEntity.ok().body(new ParsingGeoJsonResults(true, geoJson));
    }

    /**
     * 递归处理对比图层
     *
     * @param layerCode
     * @param layerCodes
     * @param middleCodes
     * @return
     * @throws IOException
     */
    private String intersectionLayer(String layerCode, List<LayerComparisonsModel> layerCodes, List<String> middleCodes) throws Exception {

        if (layerCodes.isEmpty()) {
            middleCodes.remove(layerCode);
            for (String middleCode : middleCodes) {
                postGISService.removeSchema(middleCode);
            }
            return layerCode;
        }
        ParsingShpResults result = postGISService.intersectionLayer(layerCode, layerCodes.get(0).getLayerCode(), layerCodes.get(0).getCql());
        if (result.getIsSuccess()) {
            middleCodes.add(result.getMessage());
            layerCodes.remove(0);
            return intersectionLayer(result.getMessage(), layerCodes, middleCodes);
        }
        //失败了
        for (String middleCode : middleCodes) {
            postGISService.removeSchema(middleCode);
        }
        throw new BadRequestException("intersectionLayer", "对比图层出错，出错信息为 " + result.getMessage());
    }


    @PostMapping("/publishTempLayer")
    @ApiOperation(value = "发布临时图层", notes = "发布临时图层")
    public ResponseEntity<LayerInfoResponse> publishTempLayer(@RequestBody TempLayerCreateRequest request,
                                                              @ApiIgnore @CurrentOperator SessionModel operator) throws IOException {

        ParsingShpResults result1 = postGISService.uploadShp(request.getFileId());
        if (!result1.getIsSuccess()) {
            throw new BadRequestException("importShp", result1.getMessage());
        }
        ParsingShpResults result2 = geoManagerService.releaseLayer(request.getFileId(), result1.getCrs(), request.getStyleNames(), request.getWorkSpace());
        if (!result2.getIsSuccess()) {
            throw new BadRequestException("importShp", result2.getMessage());
        }
        LayerInfoResponse layerInfoResponse = new LayerInfoResponse();
        layerInfoResponse.setLayerCode(request.getFileId());
        layerInfoResponse.setLayerSpace(request.getWorkSpace());
        layerInfoResponse.setTableName(request.getFileId());
        layerInfoResponse.setId(request.getFileId());
        return ResponseEntity.ok().body(layerInfoResponse);
    }

    @GetMapping("/tranWktCrsToWgs84")
    @ApiOperation(value = "转换其他坐标的Wkt为wgs84的wkt", notes = "转换其他坐标的Wkt为wgs84的wkt（返回 targetWkt 获取84的wkt字符串）")
    public ResponseEntity<Map<String, String>> tranWktCrsToWgs84(@RequestParam(name = "sourceWkt") String sourceWkt, @RequestParam(name = "crs") String crs) {
        String result = postGISService.tranWktCrsToWgs84(sourceWkt, crs);
        if (StringUtils.isBlank(result)) {
            throw new BadRequestException("tranWktCrsToWgs84", "转换无返回数据");
        }
        Map<String, String> map = new HashMap<>();
        map.put("targetWkt", result);
        return ResponseEntity.ok().body(map);
    }

    @PostMapping("/tranWktCrs")
    @ApiOperation(value = "转换其他坐标的Wkt为目标的wkt", notes = "转换其他坐标的Wkt为目标的wkt（返回 targetWkt 获取目标坐标系的wkt字符串）")
    public ResponseEntity<Map<String, String>> tranWktCrsToWgs84(@RequestBody WktCrsRequest request) {
        String result = postGISService.tranWktCrs(request.getSourceWkt(), request.getSourceCrs(), request.getTargetCrs());
        if (StringUtils.isBlank(result)) {
            throw new BadRequestException("tranWktCrsToWgs84", "转换无返回数据");
        }
        Map<String, String> map = new HashMap<>();
        map.put("targetWkt", result);
        return ResponseEntity.ok().body(map);
    }

}
